package com.ruoyi.workflow.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.BetweenFormatter;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.flowable.common.constant.TaskConstants;
import com.ruoyi.flowable.core.FormConf;
import com.ruoyi.flowable.factory.FlowServiceFactory;
import com.ruoyi.flowable.flow.FlowableUtils;
import com.ruoyi.flowable.utils.ModelUtils;
import com.ruoyi.flowable.utils.ProcessFormUtils;
import com.ruoyi.flowable.utils.TaskUtils;
import com.ruoyi.system.domain.SysPost;
import com.ruoyi.system.mapper.SysRoleMapper;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.workflow.domain.WfDefComponent;
import com.ruoyi.workflow.domain.WfDeployForm;
import com.ruoyi.workflow.domain.bo.WfProcessBo;
import com.ruoyi.workflow.domain.dto.WfMetaInfoDto;
import com.ruoyi.workflow.domain.vo.*;
import com.ruoyi.workflow.mapper.WfDefComponentMapper;
import com.ruoyi.workflow.mapper.WfDeployFormMapper;
import com.ruoyi.workflow.service.ISysService;
import com.ruoyi.workflow.service.IWfProcessService;
import com.ruoyi.workflow.service.IWfTaskService;
import liquibase.pro.packaged.S;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.Server;
import org.flowable.bpmn.constants.BpmnXMLConstants;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.StartEvent;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricActivityInstanceQuery;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.history.HistoricProcessInstanceQuery;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.Model;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.repository.ProcessDefinitionQuery;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.task.Comment;
import org.flowable.entitylink.api.history.HistoricEntityLink;
import org.flowable.identitylink.api.IdentityLinkInfo;
import org.flowable.identitylink.api.history.HistoricIdentityLink;
import org.flowable.identitylink.service.impl.persistence.entity.IdentityLinkEntity;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.api.history.HistoricTaskInstanceQuery;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.io.InputStream;
import java.time.Duration;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author KonBAI
 * @createTime 2022/3/24 18:57
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class WfProcessServiceImpl extends FlowServiceFactory implements IWfProcessService {

    private final IWfTaskService wfTaskService;
    private final WfDeployFormMapper deployFormMapper;
    private final WfDefComponentMapper defComponentMapper;

    private final ISysUserService userService;

    private final ISysRoleService roleService;

    private final SysUserMapper userMapper;

    private final ISysService sysService;
    private final ISysDeptService deptService;

    /**
     * 流程定义列表
     *
     * @param pageQuery 分页参数
     * @return 流程定义分页列表数据
     */
    @Override
    public TableDataInfo<WfDefinitionVo> processList(PageQuery pageQuery) {
        Page<WfDefinitionVo> page = new Page<>();
        // 流程定义列表数据查询
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery()
            .latestVersion()
            .active()
            .orderByProcessDefinitionKey()
            .asc();
        long pageTotal = processDefinitionQuery.count();
        if (pageTotal <= 0) {
            return TableDataInfo.build();
        }
        int offset = pageQuery.getPageSize() * (pageQuery.getPageNum() - 1);
        List<ProcessDefinition> definitionList = processDefinitionQuery.listPage(offset, pageQuery.getPageSize());

        List<WfDefinitionVo> definitionVoList = new ArrayList<>();
        for (ProcessDefinition processDefinition : definitionList) {
            String deploymentId = processDefinition.getDeploymentId();
            Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
            WfDefinitionVo vo = new WfDefinitionVo();
            vo.setDefinitionId(processDefinition.getId());
            vo.setProcessKey(processDefinition.getKey());
            vo.setProcessName(processDefinition.getName());
            vo.setVersion(processDefinition.getVersion());
            vo.setDeploymentId(processDefinition.getDeploymentId());
            vo.setSuspended(processDefinition.isSuspended());
            // 流程定义时间
            vo.setCategory(deployment.getCategory());
            vo.setDeploymentTime(deployment.getDeploymentTime());
            definitionVoList.add(vo);
        }
        page.setRecords(definitionVoList);
        page.setTotal(pageTotal);
        return TableDataInfo.build(page);
    }
    private String parseIdby(Map<String, Object> variables){

        // 流程定义列表数据查询
//        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
//            .latestVersion()
//            .active()
//            .orderByProcessDefinitionKey()
//            .asc().list();
        log.info("=============================="+JSONUtil.parse(variables));
        List<Model> list = repositoryService.createModelQuery().list();
        for(Model model : list){
            if(ObjectUtil.isNull(model))continue;
            WfMetaInfoDto metaInfo = JsonUtils.parseObject(model.getMetaInfo(), WfMetaInfoDto.class);
            if (ObjectUtil.isNotNull(metaInfo)) {
                String description = metaInfo.getDescription();
                if(ObjectUtil.isNull(description))continue;
                String[] descs = description.split("&");
                boolean suitable = false;
                for(int i = 0 ; i < descs.length;i ++){
                    String[] conditions = descs[i].split("<=");
                    if(conditions.length == 2){
                        if(variables.containsKey(conditions[0])){
                            Object obj = variables.get(conditions[0]);
                            if(obj instanceof Integer){
                                int i1 = (int) obj;
                                int c1 = Integer.parseInt(conditions[1]);
                                if(suitable = i1 <= c1){
                                    continue;
                                }else{
                                    break;
                                }
                            }else if(obj instanceof Double){
                                double i1 = (double) obj;
                                double c1 = Double.parseDouble(conditions[1]);
                                if(suitable = i1 <= c1){
                                    continue;
                                }else {
                                    break;
                                }
                            }
                        }
                    }
                    conditions = descs[i].split(">=");
                    if(conditions.length == 2){
                        if(variables.containsKey(conditions[0])){
                            Object obj = variables.get(conditions[0]);
                            if(obj instanceof Integer){
                                int i1 = (int) obj;
                                int c1 = Integer.parseInt(conditions[1]);
                                if(suitable = i1 >= c1){
                                    continue;
                                }else{
                                    break;
                                }
                            }else if(obj instanceof Double){
                                double i1 = (double) obj;
                                double c1 = Double.parseDouble(conditions[1]);
                                if(suitable = i1 >= c1){
                                    continue;
                                }else {
                                    break;
                                }
                            }
                        }
                    }
                    conditions = descs[i].split("<");
                    if(conditions.length == 2){
                        if(variables.containsKey(conditions[0])){
                            Object obj = variables.get(conditions[0]);
                            if(obj instanceof Integer){
                                int i1 = (int) obj;
                                int c1 = Integer.parseInt(conditions[1]);
                                if(suitable = i1 < c1){
                                    continue;
                                }else{
                                    break;
                                }
                            }else if(obj instanceof Double){
                                double i1 = (double) obj;
                                double c1 = Double.parseDouble(conditions[1]);
                                if(suitable = i1 < c1){
                                    continue;
                                }else {
                                    break;
                                }
                            }
                        }
                    }
                    conditions = descs[i].split(">");
                    if(conditions.length == 2){
                        if(variables.containsKey(conditions[0])){
                            Object obj = variables.get(conditions[0]);
                            if(obj instanceof Integer){
                                int i1 = (int) obj;
                                int c1 = Integer.parseInt(conditions[1]);
                                if(suitable = i1 > c1){
                                    continue;
                                }else{
                                    break;
                                }
                            }else if(obj instanceof Double){
                                double i1 = (double) obj;
                                double c1 = Double.parseDouble(conditions[1]);
                                if(suitable = i1 > c1){
                                    continue;
                                }else {
                                    break;
                                }
                            }
                        }
                    }
                    conditions = descs[i].split("!=");
                    if(conditions.length == 2 ){
                        if(conditions[1].contains("\"")){
                            String strVal = conditions[1].replaceAll("\"", "");
                            if(variables.containsKey(conditions[0])){
                                String[] split = strVal.split(",");
                                if(split.length == 1){
                                    if(suitable = !variables.get(conditions[0]).equals(strVal)){
                                        continue;
                                    }else{
                                        break;
                                    }
                                }else{
                                    suitable = false;
                                    for(int s = 0; s < split.length;s ++){
                                        String strV = (String) variables.get(conditions[0]);
                                        if(!strV.equals(split[s])){
                                            suitable = true;
                                            break;
                                        }
                                    }
                                    if(suitable){
                                        continue;
                                    }
                                    break;
                                }

                            }
                        }else{
                            if(variables.containsKey(conditions[0])){
                                String[] split = conditions[1].split(",");
                                if(split.length == 1){
                                    if(suitable = !variables.get(conditions[0]).equals(conditions[1])){
                                        continue;
                                    }else{
                                        break;
                                    }
                                }else{
                                    suitable = false;
                                    for(int s = 0; s < split.length;s ++){
                                        if(!variables.get(conditions[0]).equals(split[s])){
                                            suitable = true;
                                            continue;
                                        }
                                    }
                                    if(suitable){
                                        continue;
                                    }
                                    suitable = false;
                                    break;
                                }
                            }
                        }
                    }
                    conditions = descs[i].split("=");
                    if(conditions.length == 2 ){
                        if(conditions[1].contains("\"")){
                            String strVal = conditions[1].replaceAll("\"", "");
                            if(variables.containsKey(conditions[0])){
                                String[] split = strVal.split(",");
                                if(split.length == 1){
                                    if(suitable = variables.get(conditions[0]).equals(strVal)){
                                        continue;
                                    }else{
                                        break;
                                    }
                                }else{
                                    suitable = false;
                                    for(int s = 0; s < split.length;s ++){
                                        String strV = (String) variables.get(conditions[0]);
                                        if(strV.equals(split[s])){
                                            suitable = true;
                                            break;
                                        }
                                    }
                                    if(suitable){
                                        continue;
                                    }
                                    break;
                                }

                            }
                        }else{
                            if(variables.containsKey(conditions[0])){
                                String[] split = conditions[1].split(",");
                                if(split.length == 1){
                                    if(suitable = variables.get(conditions[0]).equals(conditions[1])){
                                        continue;
                                    }else{
                                        break;
                                    }
                                }else{
                                    suitable = false;
                                    for(int s = 0; s < split.length;s ++){
                                        if(variables.get(conditions[0]).equals(split[s])){
                                            suitable = true;
                                            continue;
                                        }
                                    }
                                    if(suitable){
                                        continue;
                                    }
                                    suitable = false;
                                    break;
                                }

                            }
                        }
                    }
                    throw new ServiceException(description+"表达式解释失败!请检查模型");
                }
                if(suitable)return model.getKey();
            }
        }
        JSON parse = JSONUtil.parse(variables);
        throw new ServiceException(parse+"表达式解释失败!");
    }

    @Override
    public String selectFormContent(String definitionId, String deployId) {
        InputStream inputStream = repositoryService.getProcessModel(definitionId);
        String bpmnString;
        try {
            bpmnString = IoUtil.readUtf8(inputStream);
        } catch (IORuntimeException exception) {
            throw new RuntimeException("获取流程设计失败！");
        }
        BpmnModel bpmnModel = ModelUtils.getBpmnModel(bpmnString);
        StartEvent startEvent = ModelUtils.getStartEvent(bpmnModel);
        WfDeployFormVo deployFormVo = deployFormMapper.selectVoOne(new LambdaQueryWrapper<WfDeployForm>()
            .eq(WfDeployForm::getDeployId, deployId)
            .eq(WfDeployForm::getFormKey, startEvent.getFormKey())
            .eq(WfDeployForm::getNodeKey, startEvent.getId()));
        return deployFormVo.getContent();
    }

    /**
     * 根据流程定义ID启动流程实例
     *
     * @param variables 流程变量
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void startProcess(Map<String, Object> variables) {
        try {
            String key = this.parseIdby(variables);
            if (Objects.isNull(key)) {
                throw new ServiceException("流程不存在");
            }
            log.info("流程定义key:"+key);
            List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().parentDeploymentId(key).list();
            log.info("processDefinitionKey:"+list.size());
            List<ProcessDefinition> list1 = repositoryService.createProcessDefinitionQuery().processDefinitionId(key).list();
            log.info("processDefinitionQuery:"+list1.size());
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey(key)
                .latestVersion()
                .active()
                .orderByProcessDefinitionKey()
                .asc().singleResult();
            if (Objects.isNull(processDefinition)) {
                throw new ServiceException("流程已被挂起，请先激活流程");
            }
            String bill = (String) variables.get("bill");
            if(ObjectUtil.isEmpty(bill))throw new ServiceException("缺少字段bill");
            LinkedHashMap hashMap = (LinkedHashMap) variables.get("content");
            if(ObjectUtil.isEmpty(hashMap))throw new ServiceException("缺少字段content");
            String voucherid = (String) hashMap.get("单据编号");
            if(ObjectUtil.isEmpty(voucherid))throw new ServiceException("缺少字段单据编号");
            if(variables.containsKey("content") ){
                LinkedHashMap content = (LinkedHashMap) variables.get("content");
                JSONObject jsonObject = new JSONObject(content);
                JSONArray ja = jsonObject.getJSONArray("content");
                if(ObjectUtil.isNull(ja)){
                    throw new ServiceException("缺少字段”content“");
                }
                String userName = "";
                for(int i = 0; i < ja.size();i++){
                    String s = ja.getJSONObject(i).getStr("姓名");
                    if(i == 0 ){
                        variables.put("createby",s);
                    }
                    if(ObjectUtil.isNotEmpty(s)){
                        userName += s +",";
                    }else{
                        throw new ServiceException("缺少字段”姓名“");
                    }
                }
                variables.put("userName",userName);
            }
            // 设置流程发起人Id到流程中
            this.buildProcessVariables(variables);
            String createby = (String) variables.get("createby");
            if(ObjectUtil.isNull(createby)){
                throw new ServiceException("创建人createby不能为空");
//                createby = "何柏松";
            }
            SysUser sysUser = userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getNickName, createby));
            if(ObjectUtil.isNull(sysUser))throw new ServiceException(createby+"创建人createby不存在");
            sysService.setDefaultVariables(variables,sysUser.getUserId());
            ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId(), variables);
            // 第一个用户任务为发起人，则自动完成任务
            wfTaskService.startFirstTask(processInstance, variables);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException(e.getMessage());
        }
    }
    private String parseProcDefIdBy(String type,String leixing,double day,String deptCode){
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionNameLike(type)
            .processDefinitionNameLike(leixing).latestVersion().singleResult();
        return processDefinition.getId();
    }
    /**
     * 根据流程定义ID启动流程实例
     *
     * @param procDefId 流程定义Id
     * @param variables 流程变量
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void startProcess(String procDefId, Map<String, Object> variables) {
        try {
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionId(procDefId).singleResult();
            if (Objects.nonNull(processDefinition) && processDefinition.isSuspended()) {
                throw new ServiceException("流程已被挂起，请先激活流程");
            }
            // 设置流程发起人Id到流程中
            this.buildProcessVariables(variables);
            String createby = (String) variables.get("createby");
            if(ObjectUtil.isNull(createby)){
                //throw new ServiceException("创建人createby不能为空");
                createby = "何柏松";
            }
            SysUser sysUser = userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getNickName, createby));
            if(ObjectUtil.isNull(sysUser))throw new ServiceException(createby+"创建人createby不存在");
            sysService.setDefaultVariables(variables,sysUser.getUserId());
            ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDefId, variables);
            // 第一个用户任务为发起人，则自动完成任务
            String task = wfTaskService.startFirstTask(processInstance, variables);

//            if(variables.containsKey("content") ){
//                LinkedHashMap content = (LinkedHashMap) variables.get("content");
//                JSONObject jsonObject = new JSONObject(content);
//                this.buildDefWfDefComponent(task,jsonObject.toJSONString(0));
//            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("流程启动错误");
        }
    }

    /**
     * 通过DefinitionKey启动流程
     * @param procDefKey 流程定义Key
     * @param variables 扩展参数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void startProcessByDefKey(String procDefKey, Map<String, Object> variables) {
        try {
            if (StringUtils.isNoneBlank(procDefKey)) {
                ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionKey(procDefKey).latestVersion().singleResult();
                if (processDefinition != null && processDefinition.isSuspended()) {
                    throw new ServiceException("流程已被挂起，请先激活流程");
                }
                this.buildProcessVariables(variables);
                ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(procDefKey, variables);
                wfTaskService.startFirstTask(processInstance, variables);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("流程启动错误");
        }
    }

    /**
     * 读取xml文件
     * @param processDefId 流程定义ID
     */
    @Override
    public String queryBpmnXmlById(String processDefId) {
        InputStream inputStream = repositoryService.getProcessModel(processDefId);
        try {
            return IoUtil.readUtf8(inputStream);
        } catch (IORuntimeException exception) {
            throw new RuntimeException("加载xml文件异常");
        }
    }

    /**
     * 流程详情信息
     *
     * @param procInsId 流程实例ID
     * @param deployId 流程部署ID
     * @param taskId 任务ID
     * @return
     */
    @Override
    public WfDetailVo queryProcessDetail(String procInsId, String deployId, String taskId) {
        WfDetailVo detailVo = new WfDetailVo();
        HistoricTaskInstance taskIns = historyService.createHistoricTaskInstanceQuery()
            .taskId(taskId)
            .includeIdentityLinks()
            .includeProcessVariables()
            .includeTaskLocalVariables()
            .singleResult();
        if (taskIns == null) {
            throw new ServiceException("没有可办理的任务！");
        }
        InputStream inputStream = repositoryService.getProcessModel(taskIns.getProcessDefinitionId());
        detailVo.setBpmnXml(IoUtil.readUtf8(inputStream));
        detailVo.setTaskFormData(currTaskFormData(deployId, taskIns));
        detailVo.setHistoryProcNodeList(historyProcNodeList(procInsId));
        detailVo.setProcessFormList(processFormList(procInsId, deployId, taskIns));
        detailVo.setFlowViewer(getFlowViewer(procInsId));
        detailVo.setProcVars(this.getProcessVariables(taskId));
        //detailVo.setDefForm(currTaskDefComponent(detailVo.getHistoryProcNodeList().get(detailVo.getHistoryProcNodeList().size()-2).getTaskId()));
        return detailVo;
    }

    @Override
    public TableDataInfo<WfTaskVo> queryPageOwnProcessList(PageQuery pageQuery) {
        Set<String> list = new HashSet<>();
        HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery()
            .includeProcessVariables();
        if(ObjectUtil.isNotNull(pageQuery.getName())){
            historicTaskInstanceQuery.processDefinitionNameLike("%"+pageQuery.getName()+"%");
        }
        if(ObjectUtil.isNotEmpty(pageQuery.getDeptCode())){
            historicTaskInstanceQuery.processVariableValueLike("deptcode", pageQuery.getDeptCode());
        }
        if(ObjectUtil.isNotEmpty(pageQuery.getUserName())){
            historicTaskInstanceQuery.processVariableValueLike("userName", "%"+pageQuery.getUserName()+"%");
        }
        List<HistoricTaskInstance> list1 = historicTaskInstanceQuery.list();
        list1.forEach((item)->{
            list.add(item.getProcessInstanceId());
        });
        Page<WfTaskVo> page = new Page<>();
        Long userId = LoginHelper.getUserId();
        HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery()
            .includeProcessVariables()
            .orderByProcessInstanceStartTime()
            .desc();
        if(1 != userId){
            historicProcessInstanceQuery.startedBy(userId.toString());
        }
        if(ObjectUtil.isNotEmpty(pageQuery.getUserName())
            ||ObjectUtil.isNotEmpty(pageQuery.getDeptCode())
            || ObjectUtil.isNotEmpty(pageQuery.getName())){
            if(list.size() > 0){
                historicProcessInstanceQuery.processInstanceIds(list);
            }else{
                page.setTotal(historicProcessInstanceQuery.count());
                page.setRecords(new ArrayList<>());
                return TableDataInfo.build(page);
            }
        };
        if(ObjectUtil.isNotNull(pageQuery.getDeployTime()))historicProcessInstanceQuery.startedAfter(pageQuery.getDeployTime());
        int offset = pageQuery.getPageSize() * (pageQuery.getPageNum() - 1);
        List<HistoricProcessInstance> historicProcessInstances = historicProcessInstanceQuery
            .listPage(offset, pageQuery.getPageSize());
        page.setTotal(historicProcessInstanceQuery.count());
        List<WfTaskVo> taskVoList = new ArrayList<>();
        for (HistoricProcessInstance hisIns : historicProcessInstances) {
            WfTaskVo taskVo = new WfTaskVo();
            taskVo.setCreateTime(hisIns.getStartTime());
            taskVo.setFinishTime(hisIns.getEndTime());
            taskVo.setProcInsId(hisIns.getId());

            // 计算耗时
            if (Objects.nonNull(hisIns.getEndTime())) {
                taskVo.setDuration(DateUtils.getDatePoor(hisIns.getEndTime(), hisIns.getStartTime()));
            } else {
                taskVo.setDuration(DateUtils.getDatePoor(DateUtils.getNowDate(), hisIns.getStartTime()));
            }
            // 流程部署实例信息
            Deployment deployment = repositoryService.createDeploymentQuery()
                .deploymentId(hisIns.getDeploymentId()).singleResult();
            taskVo.setDeployId(hisIns.getDeploymentId());
            taskVo.setProcDefId(hisIns.getProcessDefinitionId());
            taskVo.setProcDefName(hisIns.getProcessDefinitionName());
            taskVo.setProcDefVersion(hisIns.getProcessDefinitionVersion());
            taskVo.setCategory(deployment.getCategory());
            // 当前所处流程
            List<Task> taskList = taskService.createTaskQuery().processInstanceId(hisIns.getId()).includeIdentityLinks().list();
            if (CollUtil.isNotEmpty(taskList)) {
                taskVo.setTaskId(taskList.get(0).getId());
                taskVo.setTaskName(taskList.get(0).getName());
                List<IdentityLinkInfo> identityLinks = (List<IdentityLinkInfo>) taskList.get(0).getIdentityLinks();
                StringBuilder stringBuilder = new StringBuilder();
                for (IdentityLinkInfo identityLink : identityLinks) {
                    if ("candidate".equals(identityLink.getType())) {
                        if (StringUtils.isNotBlank(identityLink.getUserId())) {
                            SysUser user = userService.selectUserById(Long.parseLong(identityLink.getUserId()));
                            stringBuilder.append(user.getNickName()).append(",");
                        }
                    }
                }
                taskVo.setAssigneeName(stringBuilder.toString());
            } else {
                List<HistoricTaskInstance> historicTaskInstance = historyService.createHistoricTaskInstanceQuery()
                    .processInstanceId(hisIns.getId()).orderByHistoricTaskInstanceEndTime().desc().list();
                if (CollUtil.isNotEmpty(historicTaskInstance)) {
                    taskVo.setTaskId(historicTaskInstance.get(0).getId());
                }
            }
            taskVo.setProcVars(hisIns.getProcessVariables());
            taskVoList.add(taskVo);
        }
        page.setRecords(taskVoList);
        return TableDataInfo.build(page);
    }

    @Override
    public TableDataInfo<WfTaskVo> queryPageTodoProcessList(PageQuery pageQuery) {

        List<String> list = new ArrayList<>();
        HistoricTaskInstanceQuery historicTaskInstanceQuery =historyService.createHistoricTaskInstanceQuery()
            .includeProcessVariables();
        if(ObjectUtil.isNotEmpty(pageQuery.getDeptCode())){
            historicTaskInstanceQuery.processVariableValueLike("deptcode", pageQuery.getDeptCode());
        }
        if(ObjectUtil.isNotEmpty(pageQuery.getUserName())){
            historicTaskInstanceQuery.processVariableValueLike("userName", "%"+pageQuery.getUserName()+"%");
        }
        List<HistoricTaskInstance> list1 = historicTaskInstanceQuery.list();
        list1.forEach((item)->{
            list.add(item.getProcessInstanceId());
        });
        Page<WfTaskVo> page = new Page<>();
        Long userId = LoginHelper.getUserId();
        TaskQuery taskQuery = taskService.createTaskQuery()
            .active()
            .includeProcessVariables()
            .taskCandidateUser(userId.toString())
            .taskCandidateGroupIn(TaskUtils.getCandidateGroup())
            .orderByTaskCreateTime().desc();
        if(ObjectUtil.isNotNull(pageQuery.getDeployTime()))taskQuery.taskCreatedAfter(pageQuery.getDeployTime());
        if(ObjectUtil.isNotNull(pageQuery.getName()))taskQuery.processDefinitionNameLike("%"+pageQuery.getName()+"%");
        if(ObjectUtil.isNotEmpty(pageQuery.getUserName()) ||ObjectUtil.isNotEmpty(pageQuery.getDeptCode())){
            if(list.size() > 0){
                taskQuery.processInstanceIdIn(list);
            }else{
                page.setTotal(taskQuery.count());
                page.setRecords(new ArrayList<>());
                return TableDataInfo.build(page);
            }
        };
        page.setTotal(taskQuery.count());
        int offset = pageQuery.getPageSize() * (pageQuery.getPageNum() - 1);
        List<Task> taskList = taskQuery.listPage(offset, pageQuery.getPageSize());
        List<WfTaskVo> flowList = new ArrayList<>();
        for (Task task : taskList) {
            WfTaskVo flowTask = new WfTaskVo();
            // 当前流程信息
            flowTask.setTaskId(task.getId());
            flowTask.setTaskDefKey(task.getTaskDefinitionKey());
            flowTask.setCreateTime(task.getCreateTime());
            flowTask.setProcDefId(task.getProcessDefinitionId());

            flowTask.setTaskName(task.getName());
            // 流程定义信息
            ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
                .processDefinitionId(task.getProcessDefinitionId())
                .singleResult();
            flowTask.setDeployId(pd.getDeploymentId());
            flowTask.setProcDefName(pd.getName());
            flowTask.setProcDefVersion(pd.getVersion());
            flowTask.setProcInsId(task.getProcessInstanceId());

            // 流程发起人信息
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(task.getProcessInstanceId())
                .singleResult();
            SysUser startUser = userService.selectUserById(Long.parseLong(historicProcessInstance.getStartUserId()));
            flowTask.setStartUserId(startUser.getNickName());
            flowTask.setStartUserName(startUser.getNickName());
            flowTask.setStartDeptName(startUser.getDept().getDeptName());
            flowTask.setCommentList(taskService.getProcessInstanceComments(task.getProcessInstanceId()));
            // 流程变量
            flowTask.setProcVars(this.getProcessVariables(task.getId()));

            flowList.add(flowTask);
        }
        page.setRecords(flowList);
        return TableDataInfo.build(page);
    }

    @Override
    public TableDataInfo<WfTaskVo> queryPageClaimProcessList(WfProcessBo processBo, PageQuery pageQuery) {
        Page<WfTaskVo> page = new Page<>();
        Long userId = LoginHelper.getUserId();
        TaskQuery taskQuery = taskService.createTaskQuery()
            .active()
            .includeProcessVariables()
            .taskCandidateUser(userId.toString())
            .taskCandidateGroupIn(TaskUtils.getCandidateGroup())
            .orderByTaskCreateTime().desc();
        if (StringUtils.isNotBlank(processBo.getProcessName())) {
            taskQuery.processDefinitionNameLike("%" + processBo.getProcessName() + "%");
        }
        page.setTotal(taskQuery.count());
        int offset = pageQuery.getPageSize() * (pageQuery.getPageNum() - 1);
        List<Task> taskList = taskQuery.listPage(offset, pageQuery.getPageSize());
        List<WfTaskVo> flowList = new ArrayList<>();
        for (Task task : taskList) {
            WfTaskVo flowTask = new WfTaskVo();
            // 当前流程信息
            flowTask.setTaskId(task.getId());
            flowTask.setTaskDefKey(task.getTaskDefinitionKey());
            flowTask.setCreateTime(task.getCreateTime());
            flowTask.setProcDefId(task.getProcessDefinitionId());
            flowTask.setTaskName(task.getName());
            // 流程定义信息
            ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
                .processDefinitionId(task.getProcessDefinitionId())
                .singleResult();
            flowTask.setDeployId(pd.getDeploymentId());
            flowTask.setProcDefName(pd.getName());
            flowTask.setProcDefVersion(pd.getVersion());
            flowTask.setProcInsId(task.getProcessInstanceId());

            // 流程发起人信息
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(task.getProcessInstanceId())
                .singleResult();
            SysUser startUser = userService.selectUserById(Long.parseLong(historicProcessInstance.getStartUserId()));
            flowTask.setStartUserId(startUser.getNickName());
            flowTask.setStartUserName(startUser.getNickName());
            flowTask.setStartDeptName(startUser.getDept().getDeptName());

            flowList.add(flowTask);
        }
        page.setRecords(flowList);
        return TableDataInfo.build(page);
    }

    @Override
    public TableDataInfo<WfTaskVo> queryPageFinishedProcessList(PageQuery pageQuery) {
        Page<WfTaskVo> page = new Page<>();
        Long userId = LoginHelper.getUserId();
        List<String> list = new ArrayList<>();
        HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery().includeProcessVariables();
        if(ObjectUtil.isNotEmpty(pageQuery.getDeptCode())){
            historicTaskInstanceQuery.processVariableValueLike("deptcode", pageQuery.getDeptCode());
        }
        if(ObjectUtil.isNotEmpty(pageQuery.getUserName())){
            historicTaskInstanceQuery.processVariableValueLike("userName", "%"+pageQuery.getUserName()+"%");
        }
        List<HistoricTaskInstance> list1 = historicTaskInstanceQuery.list();
        list1.forEach((item)->{
            list.add(item.getProcessInstanceId());
        });
        HistoricTaskInstanceQuery taskInstanceQuery = historyService.createHistoricTaskInstanceQuery()
            .includeProcessVariables()
            .finished()
            .taskAssignee(userId.toString())
            .orderByHistoricTaskInstanceEndTime()
            .desc();
        if(ObjectUtil.isNotEmpty(pageQuery.getUserName()) ||ObjectUtil.isNotEmpty(pageQuery.getDeptCode())){
            if(list.size() > 0){
                taskInstanceQuery.processInstanceIdIn(list);
            }else{
                page.setTotal(taskInstanceQuery.count());
                page.setRecords(new ArrayList<>());
                return TableDataInfo.build(page);
            }
        };
        if(ObjectUtil.isNotNull(pageQuery.getName()))taskInstanceQuery.processDefinitionNameLike("%"+pageQuery.getName()+"%");
        if(ObjectUtil.isNotNull(pageQuery.getDeployTime()))taskInstanceQuery.taskCreatedAfter(pageQuery.getDeployTime());
        int offset = pageQuery.getPageSize() * (pageQuery.getPageNum() - 1);
        List<HistoricTaskInstance> historicTaskInstanceList = taskInstanceQuery.listPage(offset, pageQuery.getPageSize());
        List<WfTaskVo> hisTaskList = new ArrayList<>();
        for (HistoricTaskInstance histTask : historicTaskInstanceList) {
            WfTaskVo flowTask = new WfTaskVo();
            // 当前流程信息
            flowTask.setTaskId(histTask.getId());
            // 审批人员信息
            flowTask.setCreateTime(histTask.getCreateTime());
            flowTask.setFinishTime(histTask.getEndTime());
            flowTask.setDuration(DateUtil.formatBetween(histTask.getDurationInMillis(), BetweenFormatter.Level.SECOND));
            flowTask.setProcDefId(histTask.getProcessDefinitionId());
            flowTask.setTaskDefKey(histTask.getTaskDefinitionKey());
            flowTask.setTaskName(histTask.getName());

            // 流程定义信息
            ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
                .processDefinitionId(histTask.getProcessDefinitionId())
                .singleResult();
            flowTask.setDeployId(pd.getDeploymentId());
            flowTask.setProcDefName(pd.getName());
            flowTask.setProcDefVersion(pd.getVersion());
            flowTask.setProcInsId(histTask.getProcessInstanceId());
            flowTask.setHisProcInsId(histTask.getProcessInstanceId());

            // 流程发起人信息
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(histTask.getProcessInstanceId())
                .singleResult();
            SysUser startUser = userService.selectUserById(Long.parseLong(historicProcessInstance.getStartUserId()));
            flowTask.setStartUserId(startUser.getNickName());
            flowTask.setStartUserName(startUser.getNickName());
            flowTask.setStartDeptName(startUser.getDept().getDeptName());

            // 流程变量
            flowTask.setProcVars(this.getProcessVariables(histTask.getId()));

            hisTaskList.add(flowTask);
        }
        page.setTotal(taskInstanceQuery.count());
        page.setRecords(hisTaskList);
//        Map<String, Object> result = new HashMap<>();
//        result.put("result",page);
//        result.put("finished",true);
        return TableDataInfo.build(page);
    }

    /**
     * 扩展参数构建
     * @param variables 扩展参数
     */
    private void buildProcessVariables(Map<String, Object> variables) {
        String createby = (String) variables.get("createby");
        String userIdStr = LoginHelper.getUserId().toString();
        if(ObjectUtil.isNotNull(createby)){
            SysUser sysUser = userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getNickName, createby));
            if(ObjectUtil.isNotNull(sysUser)){
                userIdStr  = sysUser.getUserId().toString();
            }
        }
        identityService.setAuthenticatedUserId(userIdStr);
        variables.put(BpmnXMLConstants.ATTRIBUTE_EVENT_START_INITIATOR, userIdStr);
    }


    /**
     * 获取流程变量
     *
     * @param taskId 任务ID
     * @return 流程变量
     */
    private Map<String, Object> getProcessVariables(String taskId) {
        HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery()
            .includeProcessVariables()
            .finished()
            .taskId(taskId)
            .singleResult();
        if (Objects.nonNull(historicTaskInstance)) {
            return historicTaskInstance.getProcessVariables();
        }
        return taskService.getVariables(taskId);
    }
    /**
     * 获取当前任务默认表单信息
     */
    private WfDefComponent currTaskDefComponent(String deployId) {
        WfDefComponent defComponent = defComponentMapper.selectVoOne(new LambdaQueryWrapper<WfDefComponent>()
            .eq(WfDefComponent::getDeployId, deployId));
        return defComponent;
    }

    /**
     * 获取当前任务流程表单信息
     */
    private FormConf currTaskFormData(String deployId, HistoricTaskInstance taskIns) {
        WfDeployFormVo deployFormVo = deployFormMapper.selectVoOne(new LambdaQueryWrapper<WfDeployForm>()
            .eq(WfDeployForm::getDeployId, deployId)
            .eq(WfDeployForm::getFormKey, taskIns.getFormKey())
            .eq(WfDeployForm::getNodeKey, taskIns.getTaskDefinitionKey()));
        if (ObjectUtil.isNotEmpty(deployFormVo)) {
            FormConf currTaskFormData = JsonUtils.parseObject(deployFormVo.getContent(), FormConf.class);
            if (null != currTaskFormData) {
                currTaskFormData.setFormBtns(false);
                ProcessFormUtils.fillFormData(currTaskFormData, taskIns.getTaskLocalVariables());
                return currTaskFormData;
            }
        }
        return null;
    }

    /**
     * 获取流程表单信息（不包括当前任务节点）
     */
    private List<FormConf> processFormList(String procInsId, String deployId, HistoricTaskInstance taskIns) {
        List<FormConf> procFormList = new ArrayList<>();
        HistoricProcessInstance historicProcIns = historyService.createHistoricProcessInstanceQuery().processInstanceId(procInsId).includeProcessVariables().singleResult();
        Process process = repositoryService.getBpmnModel(historicProcIns.getProcessDefinitionId()).getMainProcess();

        buildStartFormData(historicProcIns, process, deployId, procFormList);
        buildUserTaskFormData(procInsId, deployId, process, procFormList);
        return procFormList;
    }

    private void buildStartFormData(HistoricProcessInstance historicProcIns, Process process, String deployId, List<FormConf> procFormList) {
        procFormList = procFormList == null ? new ArrayList<>() : procFormList;
        HistoricActivityInstance startInstance = historyService.createHistoricActivityInstanceQuery()
            .processInstanceId(historicProcIns.getId())
            .activityId(historicProcIns.getStartActivityId())
            .singleResult();
        StartEvent startEvent = (StartEvent) process.getFlowElement(startInstance.getActivityId());
        WfDeployFormVo startFormInfo = deployFormMapper.selectVoOne(new LambdaQueryWrapper<WfDeployForm>()
            .eq(WfDeployForm::getDeployId, deployId)
            .eq(WfDeployForm::getFormKey, startEvent.getFormKey())
            .eq(WfDeployForm::getNodeKey, startEvent.getId()));
        if (ObjectUtil.isNotNull(startFormInfo)) {
            FormConf formConf = JsonUtils.parseObject(startFormInfo.getContent(), FormConf.class);
            if (null != formConf) {
                formConf.setTitle(startEvent.getName());
                formConf.setDisabled(true);
                formConf.setFormBtns(false);
                ProcessFormUtils.fillFormData(formConf, historicProcIns.getProcessVariables());
                procFormList.add(formConf);
            }
        }
    }

    private void buildUserTaskFormData(String procInsId, String deployId, Process process, List<FormConf> procFormList) {
        procFormList = procFormList == null ? new ArrayList<>() : procFormList;
        List<HistoricActivityInstance> activityInstanceList = historyService.createHistoricActivityInstanceQuery()
            .processInstanceId(procInsId).finished()
            .activityType(BpmnXMLConstants.ELEMENT_TASK_USER)
            .orderByHistoricActivityInstanceStartTime().asc()
            .list();
        for (HistoricActivityInstance instanceItem : activityInstanceList) {
            UserTask userTask = (UserTask) process.getFlowElement(instanceItem.getActivityId(), true);
            String formKey = userTask.getFormKey();
            if (formKey == null) {
                continue;
            }
            // 查询任务节点参数，并转换成Map
            Map<String, Object> variables = historyService.createHistoricVariableInstanceQuery()
                .processInstanceId(procInsId)
                .taskId(instanceItem.getTaskId())
                .list()
                .stream()
                .collect(Collectors.toMap(HistoricVariableInstance::getVariableName, HistoricVariableInstance::getValue));
            WfDeployFormVo deployFormVo = deployFormMapper.selectVoOne(new LambdaQueryWrapper<WfDeployForm>()
                .eq(WfDeployForm::getDeployId, deployId)
                .eq(WfDeployForm::getFormKey, formKey)
                .eq(WfDeployForm::getNodeKey, userTask.getId()));
            if (ObjectUtil.isNotNull(deployFormVo)) {
                FormConf formConf = JsonUtils.parseObject(deployFormVo.getContent(), FormConf.class);
                if (null != formConf) {
                    formConf.setTitle(userTask.getName());
                    formConf.setDisabled(true);
                    formConf.setFormBtns(false);
                    ProcessFormUtils.fillFormData(formConf, variables);
                    procFormList.add(formConf);
                }
            }
        }
    }

    /**
     * 获取历史任务信息列表
     */
    private List<WfProcNodeVo> historyProcNodeList(String procInsId) {
        List<HistoricActivityInstance> historicActivityInstanceList =  historyService.createHistoricActivityInstanceQuery()
            .processInstanceId(procInsId)
            .activityTypes(CollUtil.newHashSet(BpmnXMLConstants.ELEMENT_EVENT_START, BpmnXMLConstants.ELEMENT_EVENT_END, BpmnXMLConstants.ELEMENT_TASK_USER))
            .orderByHistoricActivityInstanceStartTime().desc()
            .orderByHistoricActivityInstanceEndTime().desc()
            .list();

        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
            .processInstanceId(procInsId)
            .singleResult();

        List<Comment> commentList = taskService.getProcessInstanceComments(procInsId);

        List<WfProcNodeVo> elementVoList = new ArrayList<>();
        for (HistoricActivityInstance activityInstance : historicActivityInstanceList) {
            WfProcNodeVo elementVo = new WfProcNodeVo();
            elementVo.setTaskId(activityInstance.getTaskId());
            elementVo.setProcDefId(activityInstance.getProcessDefinitionId());
            elementVo.setActivityId(activityInstance.getActivityId());
            elementVo.setActivityName(activityInstance.getActivityName());
            elementVo.setActivityType(activityInstance.getActivityType());
            elementVo.setCreateTime(activityInstance.getStartTime());
            elementVo.setEndTime(activityInstance.getEndTime());
            if (ObjectUtil.isNotNull(activityInstance.getDurationInMillis())) {
                elementVo.setDuration(DateUtil.formatBetween(activityInstance.getDurationInMillis(), BetweenFormatter.Level.SECOND));
            }

            if (BpmnXMLConstants.ELEMENT_EVENT_START.equals(activityInstance.getActivityType())) {
                if (ObjectUtil.isNotNull(historicProcessInstance)) {
                    Long userId = Long.parseLong(historicProcessInstance.getStartUserId());
                    SysUser user = userService.selectUserById(userId);
                    if (user != null) {
                        elementVo.setAssigneeId(user.getUserId());
                        elementVo.setAssigneeName(user.getNickName());
                    }
                }
            } else if (BpmnXMLConstants.ELEMENT_TASK_USER.equals(activityInstance.getActivityType())) {
                if (StringUtils.isNotBlank(activityInstance.getAssignee())) {
                    SysUser user = userService.selectUserById(Long.parseLong(activityInstance.getAssignee()));
                    elementVo.setAssigneeId(user.getUserId());
                    elementVo.setAssigneeName(user.getNickName());
                }
                // 展示审批人员
                List<HistoricIdentityLink> linksForTask = historyService.getHistoricIdentityLinksForTask(activityInstance.getTaskId());
                StringBuilder stringBuilder = new StringBuilder();
                for (HistoricIdentityLink identityLink : linksForTask) {
                    if ("candidate".equals(identityLink.getType())) {
                        if (StringUtils.isNotBlank(identityLink.getUserId())) {
                            SysUser user = userService.selectUserById(Long.parseLong(identityLink.getUserId()));
                            stringBuilder.append(user.getNickName()).append(",");
                        }
                        if (StringUtils.isNotBlank(identityLink.getGroupId())) {
                            if (identityLink.getGroupId().startsWith(TaskConstants.ROLE_GROUP_PREFIX)) {
                                Long roleId = Long.parseLong(StringUtils.stripStart(identityLink.getGroupId(), TaskConstants.ROLE_GROUP_PREFIX));
                                SysRole role = roleService.selectRoleById(roleId);
                                stringBuilder.append(role.getRoleName()).append(",");
                            } else if (identityLink.getGroupId().startsWith(TaskConstants.DEPT_GROUP_PREFIX)) {
                                Long deptId = Long.parseLong(StringUtils.stripStart(identityLink.getGroupId(), TaskConstants.DEPT_GROUP_PREFIX));
                                SysDept dept = deptService.selectDeptById(deptId);
                                stringBuilder.append(dept.getDeptName()).append(",");
                            }
                        }
                    }
                }
                if (StringUtils.isNotBlank(stringBuilder)) {
                    elementVo.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1));
                }
                // 获取意见评论内容
                if (CollUtil.isNotEmpty(commentList)) {
                    List<Comment> comments = new ArrayList<>();
                    for (Comment comment : commentList) {

                        if (comment.getTaskId().equals(activityInstance.getTaskId())) {
                            comments.add(comment);
                        }
                    }
                    elementVo.setCommentList(comments);
                }
            }
            elementVoList.add(elementVo);
        }
        return elementVoList;
    }


    private void buildDefWfDefComponent(String deployId,String bill,String variables){
        WfDefComponent defComponent = new WfDefComponent();
        defComponent.setContent(variables);
        defComponent.setComponentName(bill);
        defComponent.setDeployId(deployId);
        defComponentMapper.insert(defComponent);
    }

    /**
     * 获取流程执行过程
     *
     * @param procInsId
     * @return
     */
    private WfViewerVo getFlowViewer(String procInsId) {
        // 构建查询条件
        HistoricActivityInstanceQuery query = historyService.createHistoricActivityInstanceQuery()
            .processInstanceId(procInsId);
        List<HistoricActivityInstance> allActivityInstanceList = query.list();
        if (CollUtil.isEmpty(allActivityInstanceList)) {
            return new WfViewerVo();
        }
        // 获取流程发布Id信息
        String processDefinitionId = allActivityInstanceList.get(0).getProcessDefinitionId();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        // 查询所有已完成的元素
        List<HistoricActivityInstance> finishedElementList = allActivityInstanceList.stream()
            .filter(item -> ObjectUtil.isNotNull(item.getEndTime())).collect(Collectors.toList());
        // 所有已完成的连线
        Set<String> finishedSequenceFlowSet = new HashSet<>();
        // 所有已完成的任务节点
        Set<String> finishedTaskSet = new HashSet<>();
        finishedElementList.forEach(item -> {
            if (BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW.equals(item.getActivityType())) {
                finishedSequenceFlowSet.add(item.getActivityId());
            } else {
                finishedTaskSet.add(item.getActivityId());
            }
        });
        // 查询所有未结束的节点
        Set<String> unfinishedTaskSet = allActivityInstanceList.stream()
            .filter(item -> ObjectUtil.isNull(item.getEndTime()))
            .map(HistoricActivityInstance::getActivityId)
            .collect(Collectors.toSet());
        // DFS 查询未通过的元素集合
        Set<String> rejectedSet = FlowableUtils.dfsFindRejects(bpmnModel, unfinishedTaskSet, finishedSequenceFlowSet, finishedTaskSet);
        return new WfViewerVo(finishedTaskSet, finishedSequenceFlowSet, unfinishedTaskSet, rejectedSet);
    }



}
